#include "logger.h"
#include "setproctitle.h"
#include "httpserver.h"
#include "logger.h"
#include "hook.h"

using namespace std;
using namespace nmsp;

extern int *g_write_fd;
extern int *g_read_fd;

#define HTTPSERVER "httpserver"
#define HTTPSERVER_PORT 8989
#define PARENT_PROTITLE "read_pipe"
#define CHILD_PROTITLE "httpserver"


INITIALIZE_EASYLOGGINGPP;

// 
// $ ps -ef | grep read_pipe  #==> zhangxi     6155    6125  0 19:43 pts/5    00:00:00 read_pipe
// $ ps -ef | grep httpserver #==> zhangxi     6156    6155  0 19:43 pts/5    00:00:00 httpserver
// 
// "http://10.4.7.128:8989/hi"  响应 Hello World!
// 



int main(int argc, char const *argv[])
{
    {
        // 只需要在 main() 开始时候初始化一次就够, 当然后续根据子集需要  defaultConf.set()  el::Loggers::reconfigureLogger,
        // defaultConf.setGlobally()   el::Loggers::reconfigureLogger(),
        el::Configurations defaultConf;
        defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%datetime %level %msg");
        defaultConf.setGlobally(el::ConfigurationType::Filename, "../log/log_%datetime{%Y%M%d_%H%m%s}.log");
        el::Loggers::reconfigureLogger("default", defaultConf);
    }

    MYLOG("httpserver start ...")

    int fd[2];
    pid_t httpserverpid;
    {
        // 开启一个 httpserver, 以供测试使用,

        g_write_fd = &fd[1];
        g_read_fd = &fd[0];
        if (-1 == pipe(fd))
        {
            MYLOG("create pipe error!");
            exit(1);
        }

        switch (fork())
        {
        case -1:
            MYLOG("main()", "%s", strerror(errno));
            exit(-1);
        case 0:
            // 子进程 开启一个 httpserver , 接收 curl 等测试,
            close(*g_read_fd);
            httpserverpid = getpid();

            std::thread([]()
                        { 
                while(true)
                {
                    // 类似 ngx master worker, 监测父进程, 如果master已经退出, worker 就退出,
                    if(1 == getppid()) {exit(0);}
                    this_thread::sleep_for(std::chrono::milliseconds(1000));
                } })
                .detach();

            // 子进程业务, httpserver.Listen() 会阻塞住,
            {
                g_os_argv = (char **)argv;
                InitSetProcTitle();
                SetProcTitle(CHILD_PROTITLE);

                Httpserver httpserver;
                if (0 == httpserver.Register())
                    httpserver.Listen("0.0.0.0", HTTPSERVER_PORT);
            }

        default:
            // 父进程 直接break,
            {
                g_os_argv = (char **)argv;
                InitSetProcTitle();
                SetProcTitle(PARENT_PROTITLE);

                close(*g_write_fd);
            }
            break;
        }
    }

    if (getpid() == httpserverpid)
    {
        // 正常流程是不会走到这里的,
        MYLOG("main()", "httpserverpid error, there is mustbe parentpid");
        if (gp_envmem)
        {
            delete[] gp_envmem;
            gp_envmem = NULL;
        }

        exit(1);
    }

    // 父进程捕获 SIGCHLD 信号, 同时捕获 Ctrl+C 等信号, 当父进程要要退出时候, 给子进程发送 "http://127.0.0.1:8989/stop" , 让子进程也退出,
    // 子进程捕获 SIGHUP 信号, 这样父进程退出时候, 子进程 exit(0) 也退出,

    std::thread([]()
                {
        // 接受子进程的消息, httpserver 是 子进程, client 是父进程,
        while (1)
        {
            this_thread::sleep_for(std::chrono::milliseconds(2000));
            char readbuffer[128];

            if (g_read_fd != NULL)
            {
                int nbytes = read(*g_read_fd, readbuffer, sizeof(readbuffer) - 1);
                printf("recv nbytes = %d , context is \"%s\"\n", nbytes, readbuffer);
                MYLOG("recv nbytes = %d , context is \"%s\"\n", nbytes, readbuffer);
            }
        } })
        .join();

    MYLOG("%s", "release gp_envmem");

    if (gp_envmem)
    {
        delete[] gp_envmem;
        gp_envmem = NULL;
    }

    return 0;
}
